/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Optimizacion;

import java.util.ArrayList;

/**
 *
 * @author REI
 */
public class OptimizacionMirilla {
    
    ArrayList globales = new ArrayList();

    public boolean simplificacion_algebraica(ArrayList lista, int globales) {
        boolean cambio = false;
        if (!lista.isEmpty()) {

            if (lista.size() <= 12) {
                if (lista.size() >= 2) {
                    for (int i = 0; i < lista.size() - 1; i++) {
                        if (aplicar_optimizacion1(lista, i, globales) == true) {
                            i = 0;
                            cambio = true;
                        }
                    }
                }
            } else {//si son mas de 12 lineas
                for (int i = 0; i < lista.size() - 1; i = i + 12) {
                    int limite = i + 11;
                    if (limite > (lista.size() - 1)) {
                        limite = lista.size() - 1;
                    }

                    for (int j = i; j < limite; j++) {
                        if (aplicar_optimizacion1(lista, j, globales) == true) {
                            j = i;
                            cambio = true;
                        }
                    }
                }
            }
        }
        return cambio;
    }

    public boolean aplicar_optimizacion1(ArrayList lista, int i, int globales) {
        try{
        String linea1 = lista.get(i).toString().trim();
        
        if (linea1.indexOf("#") == -1&&linea1.indexOf("()") == -1 && linea1.indexOf(":") == -1 && !linea1.toUpperCase().startsWith("GOTO") && !linea1.toUpperCase().startsWith("HEAP") && !linea1.toUpperCase().startsWith("PILA") && !linea1.toUpperCase().startsWith("IF")  && !linea1.toUpperCase().startsWith("INT")&&!linea1.toUpperCase().startsWith("FLOAT") &&!linea1.toUpperCase().startsWith("USING")&&!linea1.toUpperCase().startsWith("COUT")&&!linea1.toUpperCase().startsWith("TX")&& !linea1.toUpperCase().startsWith("RETURN")&& !linea1.toUpperCase().startsWith("OFS") && !linea1.toUpperCase().startsWith("STD")&& !linea1.toUpperCase().startsWith("CHAR NOMBRE")) {
            //el () es por las llamadas de funcion;
            //los : es por las etiquetas
            
            String[] div1 = linea1.split("=");
            String valor = div1[1].trim();
            String temporal = div1[0].trim();
            if (!valor.toUpperCase().startsWith("HEAP") && !valor.toUpperCase().startsWith("PILA")&& !valor.toUpperCase().startsWith("COUT")) {//se verifica que no sea un acceso al HEAP o PILA
                if (valor.indexOf("+") == -1 && valor.indexOf(" - ") == -1 && valor.indexOf("*") == -1 && valor.indexOf("/") == -1 && valor.indexOf("%") == -1  ) {
                    //si del lado derecho del =  no es una operacion, indica q es un temporal o variable

                    String linea2 = lista.get(i + 1).toString().trim();
                    if (linea2.indexOf("#") == -1&&linea2.indexOf("()") == -1 && linea2.indexOf(":") == -1 && !linea2.toUpperCase().startsWith("GOTO") && !linea2.toUpperCase().startsWith("HEAP") && !linea2.toUpperCase().startsWith("PILA") && !linea2.toUpperCase().startsWith("IF")  && !linea2.toUpperCase().startsWith("INT")&&!linea2.toUpperCase().startsWith("FLOAT") &&!linea2.toUpperCase().startsWith("USING")&&!linea2.toUpperCase().startsWith("COUT")&&!linea2.toUpperCase().startsWith("TX")&& !linea2.toUpperCase().startsWith("RETURN")&& !linea2.toUpperCase().startsWith("OFS") && !linea2.toUpperCase().startsWith("STD")&& !linea2.toUpperCase().startsWith("CHAR NOMBRE")) {
                        
                        String[] div2 = linea2.split("=");
                        String valor2 = div2[1].trim();

                        if (valor2.indexOf(temporal+"") != -1) {
                            valor2 = valor2.replace(temporal+"", valor.replace(";", ""));
                            lista.set(i + 1, div2[0] + "= " + valor2);
//                            lista.remove(i);
                            i = i +1;
                            /*if (globales != 1) {
                            lista.remove(i);
                            }*/
                            return true;
                        }

                    }

                }
            }
        }
        }catch(NullPointerException ex){
            System.out.println("problema con :"+i);
        }
        return false;
    }

    public boolean goto_consecutivos(ArrayList lista) {
        boolean cambio = false;
        if (!lista.isEmpty()) {
            if (lista.size() <= 12) {
                if (lista.size() >= 2) {
                    for (int i = 0; i < lista.size() - 1; i++) {
                        if (aplicar_optimizacion2(lista, i) == true) {
                            i = 0;
                            cambio = true;
                        }
                    }
                }
            } else {//si son mas de 12 lineas
                for (int i = 0; i < lista.size() - 1; i = i + 12) {
                    int limite = i + 11;
                    if (limite > (lista.size() - 1)) {
                        limite = lista.size() - 1;
                    }
                    for (int j = i; j < limite; j++) {
                        if (aplicar_optimizacion2(lista, j) == true) {
                            j = j-1;
                            cambio = true;
                        }
                    }
                }
            }
        }
        return cambio;
    }

    public boolean aplicar_optimizacion2(ArrayList lista, int i) {

        String linea1 = lista.get(i).toString().trim();
        if (linea1.toUpperCase().startsWith("GOTO")) {//si la linea es un Goto Lx;

            String etiqueta1 = get_nombre_etq(linea1);//se obtiene el nombre de la Etiqueta
            etiqueta1 = etiqueta1.replace(";", " ");
            String linea2 = lista.get(i + 1).toString().trim();//se obtiene la siguiente linea
            if (linea2.indexOf(":") != -1) {//se compara si la siguiente linea es Etiqueta
                if (linea2.indexOf(etiqueta1+" ") != -1) {//se verifica que la siguiente linea coincida con la Etiqueta
                    lista.remove(i);
                    return true;
                }

            }
        }
        return false;
    }

    public boolean flujos_de_ejecucion(ArrayList lista) {

        if (!lista.isEmpty()) {
            if (lista.size() <= 12) {
                if (lista.size() >= 3) {
                    for (int i = 0; i < lista.size() - 2; i++) {
                        if (aplicar_optimizacion3(lista, i) == true) {
                            return true;
                        }
                    }
                }
            } else {//si son mas de 12 lineas
                for (int i = 0; i < lista.size() - 2; i = i + 12) {
                    int limite = i + 10;
                    if (limite > (lista.size() - 2)) {
                        limite = lista.size() - 2;
                    }
                    for (int j = i; j < limite; j++) {
                        if (aplicar_optimizacion3(lista, j) == true) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    public boolean aplicar_optimizacion3(ArrayList lista, int i) {

        String linea1 = lista.get(i).toString().trim();
        if (linea1.toUpperCase().startsWith("IF")) {//si la linea es un IF;

            String condicion = linea1.substring(linea1.indexOf("if") + 2, linea1.indexOf(")")).trim();//se obtiene la condicion
             condicion = condicion.replace("(","");
             condicion = condicion.replace(")","");
            if (condicion.indexOf("==") != -1) {
                String[] valores = condicion.split("==");
                String var1 = valores[0].trim();
                String var2 = valores[1].trim();
                if (((var1.compareTo("1.0") == 0 ||var1.compareTo("1") == 0) && (var2.compareTo("1.0") == 0 ||var2.compareTo("1") == 0)) || ((var1.compareTo("0.0") == 0 ||var1.compareTo("0") == 0) && (var2.compareTo("0.0") == 0 ||var2.compareTo("0") == 0))) {
                    String linea2 = lista.get(i + 1).toString().trim();//se obtiene la siguiente linea
                    if (linea2.toUpperCase().startsWith("GOTO")) {//si la linea es un Goto Lx;
                        String linea3 = lista.get(i + 2).toString().trim();//se obtiene la tercera linea
                        if (linea3.indexOf(":") != -1) {//si es de etiquea(s)
                            String etiquetaV = get_nombre_etq(linea1);//se obtiene el nombre de la Etiqueta V, en linea1
                            if (linea3.indexOf(",") != -1) {//si es una lista de etiquetas, se separan
                                if (linea3.indexOf(etiquetaV+" ") != -1) {//se verifica que la etqV se encuentre en la lista de etiquetas
                                    String[] lista_etq = linea3.replace(":", "").split(",");
                                    String nueva_lista = "";
                                    if (lista_etq[0].trim().compareTo(etiquetaV) != 0) {//se verifica la primer etq
                                        nueva_lista = lista_etq[0];
                                    }
                                    for (int j = 1; j < lista_etq.length; j++) {
                                        if (lista_etq[j].trim().compareTo(etiquetaV) != 0) {//se compara las demas etq
                                            nueva_lista = nueva_lista + " , " + lista_etq[j];
                                        }
                                    }

                                    lista.set(i + 2, nueva_lista + " : ");//se setea la nueva lista de etq, sin la etqV
                                    for (int j = 0; j < 2; j++) {
                                        lista.remove(i);//primero, se elimina el ID
                                        //segundo, se elimina el goto LF
                                    }
                                    return true;
                                }
                            } else {
                                String etq = linea3.replace(":", "").trim();
                                if (etq.compareTo(etiquetaV) == 0) {
                                    for (int j = 0; j < 3; j++) {
                                        lista.remove(i);//primero, se elimina el ID
                                        //segundo, se elimina el goto LF
                                        //tercero, se elimina la etqV
                                    }
                                    return true;
                                }
                            }
                        }

                    }
                }

            }
        }
        return false;
    }

    public boolean codigo_inalcanzable(ArrayList lista) {

        if (!lista.isEmpty()) {
            if (lista.size() <= 12) {
                if (lista.size() >= 4) {
                    for (int i = 0; i < lista.size() - 3; i++) {
                        if (aplicar_optimizacion4(lista, i) == true) {
                            return true;
                        }
                    }
                }
            } else {//si son mas de 12 lineas
                for (int i = 0; i < lista.size() - 3; i = i + 12) {
                    int limite = i + 9;
                    if (limite > (lista.size() - 3)) {
                        limite = lista.size() - 3;
                    }
                    for (int j = i; j < limite; j++) {
                        if (aplicar_optimizacion4(lista, j) == true) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    public boolean aplicar_optimizacion4(ArrayList lista, int i) {

        String linea1 = lista.get(i).toString().trim();
        if (linea1.toUpperCase().startsWith("IF")) {//si la linea es un IF;

            String condicion = linea1.substring(linea1.indexOf("if") + 2, linea1.indexOf(")")).trim();//se obtiene la condicion

            if (condicion.indexOf("==") != -1) {
                condicion = condicion.replace("(","");
                condicion = condicion.replace(")","");
                String[] valores = condicion.split("==");
                String var1 = valores[0].trim();
                String var2 = valores[1].trim();
                if (((var1.compareTo("1.0") == 0 || var1.compareTo("1") == 0  ) && (var2.compareTo("0.0") == 0||var2.compareTo("0") == 0)) || ((var1.compareTo("0.0") == 0||var1.compareTo("0") == 0) && (var2.compareTo("1.0") == 0 || var2.compareTo("1") == 0))) {
                    String linea2 = lista.get(i + 1).toString().trim();//se obtiene la siguiente linea
                    if (linea2.toUpperCase().startsWith("GOTO")) {//si la linea es un Goto Lx;
                        String linea3 = lista.get(i + 2).toString().trim();//se obtiene la tercera linea
                        if (linea3.indexOf(":") != -1) {//si es de etiquea(s)

                            String etiquetaV = get_nombre_etq(linea1);//se obtiene el nombre de la Etiqueta V, en linea1
                            if (linea3.indexOf(",") != -1) {//si es una lista de etiquetas
                                if (linea3.indexOf(etiquetaV+" ") != -1) {//se verifica que la etqV se encuentre en la lista de etiquetas
                                    String[] lista_etq = linea3.replace(":", "").split(",");
                                    String nueva_lista = "";
                                    if (lista_etq[0].trim().compareTo(etiquetaV) != 0) {//se verifica la primer etq
                                        nueva_lista = lista_etq[0];
                                    }
                                    for (int j = 1; j < lista_etq.length; j++) {
                                        if (lista_etq[j].trim().compareTo(etiquetaV) != 0) {//se compara las demas etq
                                            nueva_lista = nueva_lista + " , " + lista_etq[j];
                                        }
                                    }

                                    lista.set(i + 2, nueva_lista + " : ");//se setea la nueva lista de etq, sin la etqV

                                    lista.remove(i);//se elimina la linea del IF
                                    return true;
                                }
                            } else {//si es solo una etiqueta
                                String etq = linea3.replace(":", "").trim();
                                if (etq.compareTo(etiquetaV) == 0) {//se verifica que sea la etqV
                                    //luego se busca la etqF y que no halla alguna otra etiqueta entre etqV y etqF, ni goto
                                    String etiquetaF = get_nombre_etq(linea2);//se obtiene el nombre de la Etiqueta F, en linea2
                                    etiquetaF = etiquetaF.replace(";"," ");
                                    for (int j = i + 3; j < i + 12; j++) {
                                        String linea4 = lista.get(j).toString().trim();//se obtiene la cuarta linea
                                        if (linea4.toUpperCase().startsWith("GOTO")) {
                                            return false;
                                        } else {
                                            if (linea4.indexOf(":") != -1) {//si es de etiquea(s)
                                                //se verifica que la etqF se encuentre en esa linea
                                                if (linea4.indexOf(etiquetaF+"") != -1) {//si es una lista de etiquetas donde esta la Etiqueta F
                                                    for (int k = 0; k <= j - i; k++) {
                                                        lista.remove(i);
                                                    }
                                                    return true;
                                                }
                                            }
                                        }

                                    }
                                }
                            }
                        }

                    }
                }

            }
        }
        return false;
    }

    public String get_nombre_etq(String linea) {
        return linea.substring(linea.toUpperCase().indexOf("GOTO") + 4, linea.length()).trim();
    }
    
}
